package com.gsit.expenditure.controller;

import java.math.BigDecimal;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Set;

import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.util.StringConverter;
import javafx.util.converter.DoubleStringConverter;
import javafx.util.converter.IntegerStringConverter;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import com.gsit.expenditure.client.domina.BillBean;
import com.gsit.expenditure.client.domina.FXMLBase;
import com.gsit.expenditure.client.domina.TravelbillBean;
import com.gsit.expenditure.domain.Customer;
import com.gsit.expenditure.domain.TravelBill;
import com.gsit.expenditure.domain.Vehicle;
import com.gsit.expenditure.services.BillService;
import com.gsit.expenditure.utils.AppContextLoader;
import com.gsit.expenditure.utils.BillStatus;
import com.gsit.expenditure.utils.Page;
import com.gsit.expenditure.utils.Utils;
import com.gsit.expenditure.utils.ViewHandler;

import eu.schudt.javafx.controls.calendar.DatePicker;

public class TravelbillController extends BaseController implements Initializable{

	@FXML private ComboBox<Customer> customerName;
	@FXML private ComboBox<Vehicle> vehicleName;
	@FXML private TextField refNo;
	@FXML private TextField particulars;
	//DATE
	@FXML private HBox dateHbox;
	@FXML private DatePicker date;
	
	@FXML private TextField distance;
	@FXML private TextField days;
	@FXML private TextField source;
	@FXML private TextField destination;
	@FXML private TextField rate;
	@FXML private TextField amount;
	
	//Error Label
	@FXML private Label custNameErrorLabel;
	@FXML private Label vehicleNameErrorLabel;
	@FXML private Label refNoErrorLabel;
	@FXML private Label particErrorLabel;
	@FXML private Label dateErrorLabel;
	@FXML private Label distanceErrorLabel;
	@FXML private Label daysErrorLabel;
	@FXML private Label sourceErrorLabel;
	@FXML private Label destiErrorLabel;
	
	private SimpleDateFormat formatter;
	private Validator validator;
	
	@FXML private Button saveButton;
	
	private BillService billService;
	
	private TravelbillBean travelbillBean;
	private TravelBill travelBill ;
	Date selectedDate;
	
	@Override
	public void initialize(URL url, ResourceBundle bundle) {
		
		billService=AppContextLoader.getBean(BillService.class);
		travelbillBean = new TravelbillBean(null);
		
		vehicleName.getItems().addAll(billService.findVehicleName());
		customerName.getItems().addAll(billService.findCustomerName());
		
		//ADD DATE PICKER
		dateHbox.getChildren();
		date = new DatePicker(Locale.ENGLISH);
		date.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
		date.getCalendarView().todayButtonTextProperty().set("Today");
		date.getCalendarView().setShowWeeks(false);
		date.getStylesheets().add("css/datepicker/DatePicker.css");
		dateHbox.getChildren().add(date);
		
		
		//CONVERTER FOR vehicleName FIELD
		vehicleName.setConverter(new StringConverter<Vehicle>() {
			@Override
			public String toString(Vehicle vehicle) {
				return vehicle.getVehicleName();
			}
			
			@Override
			public Vehicle fromString(String vehicleName) {
				List<Vehicle> vehicles = billService.findVehicleName();
				Vehicle mVehicle = null;
				for (Vehicle vehicle : vehicles) {
					if (vehicle.getVehicleName().equals(vehicleName)) {
						mVehicle = vehicle;
						break;
					}
				}
				return mVehicle;
			}
		});
			
		// CONVERTER FOR customername FIELD
		customerName.setConverter(new StringConverter<Customer>() {
			@Override
			public String toString(Customer customer) {
				return customer.getFirstName();
			}

			@Override
			public Customer fromString(String customerName) {
				List<Customer> customers = billService.findCustomerName();
				Customer customer = null;
				for (Customer customer2 : customers) {
					if (customer2.getFirstName().equals(customerName)) {
						System.out.println("Customer FirstName>>>>>>>>>>>>>>"+ customerName);
						customer = customer2;
						break;
					}
				}
				return customer;
			}
		});
		
		//distance listener to show rate 	
		distance.textProperty().addListener(new ChangeListener<String>() {

			@Override
			public void changed(ObservableValue<? extends String> arg0,String arg1, String arg2) {

				BigDecimal total = new BigDecimal(distance.getText());
				total = total.multiply(new BigDecimal(rate.getText()));
				System.out.println(">>>>>>>>> value changeing ........"
						+ total.doubleValue());
				travelbillBean.getAmount().set(total.doubleValue());
			}

		});
			
		bind();
	}
	
	private void init() {
		if (this.travelbillBean.getTravelBill() == null)
			return;
		this.travelBill = this.travelbillBean.getTravelBill();
		refNo.setText(travelBill.getReferenceNumber());
		particulars.setText(travelBill.getParticulars());
		distance.setText(""+travelBill.getDistance());
		days.setText(""+travelBill.getDays());
		date.setSelectedDate(travelBill.getBillDate());
		source.setText(travelBill.getSource());
		destination.setText(travelBill.getDestination());
		rate.setText(""+travelBill.getRate());
		customerName.setValue(travelBill.getCustomer());
		vehicleName.setValue(travelBill.getVehicle());
		amount.setText(""+travelBill.getAmount());
	}

	
	public void doChange(){
		
		Vehicle newValue = vehicleName.getSelectionModel().getSelectedItem();
		if(newValue != null){
			travelbillBean.setRate(newValue.getRate());
		}
	}
	
	public void bind(){

		Bindings.bindBidirectional(travelbillBean.getCustomerName(), new SimpleObjectProperty<>(customerName.getSelectionModel().getSelectedItem()) );
		System.out.println("CustomerName>>>>>>>>>>>>>"+customerName.getSelectionModel().getSelectedItem());
		
		Bindings.bindBidirectional(travelbillBean.getVehicleName(),new SimpleObjectProperty<>(vehicleName.getSelectionModel().getSelectedItem()));
		System.out.println("VehicleName>>>>>>>>>>>>>"+vehicleName.itemsProperty());
		
		Bindings.bindBidirectional(travelbillBean.getRefNo(), refNo.textProperty());
		Bindings.bindBidirectional(travelbillBean.getParticulars(), particulars.textProperty());
		Bindings.bindBidirectional(travelbillBean.getSource(), source.textProperty());
		Bindings.bindBidirectional(travelbillBean.getDestination(), destination.textProperty());
		StringConverter integerConverter=new IntegerStringConverter();
		StringConverter doublerConverter=new DoubleStringConverter();
		Bindings.bindBidirectional(days.textProperty(),travelbillBean.getDays(),integerConverter);
		Bindings.bindBidirectional(rate.textProperty(),travelbillBean.getRateProperty(),doublerConverter);
		Bindings.bindBidirectional(distance.textProperty(),travelbillBean.getDistance(),doublerConverter);
		Bindings.bindBidirectional(amount.textProperty(), travelbillBean.getAmount(), doublerConverter);
		System.out.println(">>>>>>>>>Amount>>>>>>>>>>>>>"+travelbillBean.getAmount());
		
	}
	
    @Override
	public void onSave(){
    	
    	Boolean isUpdate = Boolean.FALSE;
    	
	    travelbillBean.setCustomerName(new SimpleObjectProperty<>(customerName.getSelectionModel().getSelectedItem()) );
	    travelbillBean.setVehicleName(new SimpleObjectProperty<>(vehicleName.getSelectionModel().getSelectedItem()));
	
	 	TravelBill travelBill = travelbillBean.getObject();
	    
		if(isValidate(travelBill)){
			if (date.getSelectedDate()!=null) {
				if (date.getSelectedDate().after(new java.util.Date())) {
					dateErrorLabel.setText("Should not be future date");
					
				}else{
			selectedDate = date.getSelectedDate();
		   	travelBill.setBillDate(selectedDate);
		   	travelBill.setCreatedDate(Utils.getCurrentDate());
			travelBill.setModifiedDate(Utils.getCurrentDate());
		   	travelBill.setStatus(BillStatus.NEW);
		    travelBill.setVersion(1L);
		   	
		    travelbillBean.setCustomerName(new SimpleObjectProperty<>(customerName.getSelectionModel().getSelectedItem()) );
		    System.out.println("Selected CustomerName>>>>>>>>>>>>>"+customerName.getSelectionModel().getSelectedItem());
		    
		    travelbillBean.setVehicleName(new SimpleObjectProperty<>(vehicleName.getSelectionModel().getSelectedItem()));
		    System.out.println("Selected VehicleName>>>>>>>>>>>>>"+vehicleName.getSelectionModel().getSelectedItem());
		    
		   	if (travelBill.getId() != null && travelBill.getId().longValue() > 0) {
				isUpdate = Boolean.TRUE;

				Date selectedDate = date.getSelectedDate();
				travelBill.setBillDate(selectedDate);
				travelBill.setModifiedDate(Utils.getCurrentDate());
				//travelBill.setStatus(BillStatus.NEW);
				//travelBill.setVersion(1L);
				billService.saveOrUpdateBill(travelBill);
			} else {

				Date selectedDate = date.getSelectedDate();
				travelBill.setBillDate(selectedDate);
				travelBill.setCreatedDate(Utils.getCurrentDate());
				travelBill.setModifiedDate(Utils.getCurrentDate());
				travelBill.setStatus(BillStatus.NEW);
				// travelBill.setVersion(1L);
				billService.saveOrUpdateBill(travelBill);
				
				showTravelBillPopup(travelBill);
				onClear();
			}
				}
			
			if(isUpdate){
				stateChange.set(Boolean.TRUE);
			}
				}

		}
	}
	@Override
	public void onClear(){
		System.out.println(">>>>>>. onClear >>>>>>>");
		travelbillBean.clean();
	}
private void showTravelBillPopup(TravelBill travelBill){

	final FXMLBase<SuccessController> fxmlBase =  ViewHandler.createFXMLBase(Page.SUCCESS_MSG);
	fxmlBase.getController().getStateChange().addListener(new ChangeListener<Boolean>() {
		@Override
		public void changed(ObservableValue<? extends Boolean> arg0,Boolean oldVal, Boolean newVal) {
			if(newVal){
				fxmlBase.getDialogStage().hide();
			}
		}
	});


	ViewHandler.createDialog(fxmlBase, "Bill generated successfully");
fxmlBase.getDialogStage().showAndWait();
}

	public Boolean isValidate(TravelBill travelBill){
		clearAllErrorLabels();
		Boolean result = Boolean.TRUE;
		if(validator == null){
			validator=Validation.buildDefaultValidatorFactory().getValidator();
		}
		travelBill.setBillDate(date.getSelectedDate());
		
		Set<ConstraintViolation<TravelBill>> constraintViolations = validator.validate(travelbillBean.getObject());
		System.out.println("Error Values>>>>>>>>>>"+travelBill);
		
		for (ConstraintViolation<TravelBill> constraintViolation : constraintViolations) {
			if (date.getSelectedDate()!=null) {
			if (date.getSelectedDate().after(new java.util.Date())) {
				dateErrorLabel.setText("Should not be fucture date");
			}
			}
			if (customerName.getSelectionModel().getSelectedItem()==null) {
				custNameErrorLabel.setText("Select Customer Name");
			}
			if (vehicleName.getSelectionModel().getSelectedItem()==null) {
				vehicleNameErrorLabel.setText("Select Vehicle Name");
			}
			if("referenceNumber".equalsIgnoreCase(constraintViolation.getPropertyPath().toString())){
				refNoErrorLabel.setText(constraintViolation.getMessage());
				result = Boolean.FALSE;
			}
			if("particulars".equalsIgnoreCase(constraintViolation.getPropertyPath().toString())){
				particErrorLabel.setText(constraintViolation.getMessage());
				result = Boolean.FALSE;
			}
			if("billDate".equalsIgnoreCase(constraintViolation.getPropertyPath().toString())){
				dateErrorLabel.setText(constraintViolation.getMessage());
				result = Boolean.FALSE;
			}
			if("distance".equalsIgnoreCase(constraintViolation.getPropertyPath().toString())){
				distanceErrorLabel.setText(constraintViolation.getMessage());
				result = Boolean.FALSE;
			}
			if("days".equalsIgnoreCase(constraintViolation.getPropertyPath().toString())){
				daysErrorLabel.setText(constraintViolation.getMessage());
				result = Boolean.FALSE;
			}
			if("source".equalsIgnoreCase(constraintViolation.getPropertyPath().toString())){
				sourceErrorLabel.setText(constraintViolation.getMessage());
				result = Boolean.FALSE;
			}
			if("destination".equalsIgnoreCase(constraintViolation.getPropertyPath().toString())){
				destiErrorLabel.setText(constraintViolation.getMessage());
				result = Boolean.FALSE;
			}
			}
			return result;
	   }
	
	private void clearAllErrorLabels() {
		custNameErrorLabel.setText("");
		vehicleNameErrorLabel.setText("");
		refNoErrorLabel.setText("");
		particErrorLabel.setText("");
		dateErrorLabel.setText("");
		distanceErrorLabel.setText("");
		daysErrorLabel.setText("");
		sourceErrorLabel.setText("");
		destiErrorLabel.setText("");

	}


	  public void reLoad(TravelbillBean billBean) {
			this.travelbillBean = billBean;
			init();
			
	}
	/*  public int isBeforeCurrent(Date inputDate)
	    {
	    int n=0;
	    Date d1=new Date();
	        formatter = new SimpleDateFormat("yyyy/MM/dd");
	        try{
	           Date d2 =formatter.parse(selectedDate);
	           n=d1.compareTo(d2);
	           }
	        catch(Exception pe){System.out.println(pe);}
	        return n;
	 } 
*/

	
	}
